package com.nineclock.system.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSON;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.nineclock.common.constant.MessageConstant;
import com.nineclock.common.entity.PageResult;
import com.nineclock.common.enums.ResponseEnum;
import com.nineclock.common.exception.NcException;
import com.nineclock.common.threadlocal.CurrentUserHolder;
import com.nineclock.common.utils.BeanHelper;
import com.nineclock.message.dto.SysAllowedJoinCompanyUserDTO;
import com.nineclock.message.pojo.NcMessage;
import com.nineclock.model.dto.SysCompanyUserDTO;
import com.nineclock.model.dto.SysDepartmentDTO;
import com.nineclock.model.dto.SysRoleDTO;
import com.nineclock.model.pojo.*;
import com.nineclock.system.config.HxImManager;
import com.nineclock.system.excel.ExcelMember;
import com.nineclock.system.listener.ExcelMemberListener;
import com.nineclock.system.mapper.*;
import com.nineclock.system.service.SysCompanyUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Service
@Slf4j
@Transactional
public class SysCompanyUserServiceImpl implements SysCompanyUserService  {

    @Autowired
    SysCompanyUserMapper companyUserMapper;

    @Autowired
    SysCompanyUserRoleMapper companyUserRoleMapper;

    @Autowired
    SysRoleMapper roleMapper;

    /**
     * 登录后选择企业了,根据企业id去查询,如果就一个企业就带会用户id,直接进入页面
     * 记得携带权限信息,后面鉴权,不是管理员不能登录
     * @param companyId 企业id
     * @param userId 员工id
     * @return
     */
    @Override
    public List<SysCompanyUserDTO> queryCompanyUser(Long companyId, Long userId) {

        if (companyId == null && userId == null) {
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }

        LambdaQueryWrapper<SysCompanyUser> companyUserQw = new LambdaQueryWrapper<>();

        if (userId!= null) {
            companyUserQw.eq(SysCompanyUser::getUserId,userId);
        }
        if (companyId!=null) {
            companyUserQw.eq(SysCompanyUser::getCompanyId,companyId);
        }
        companyUserQw.eq(SysCompanyUser::getEnable, 1);
        //查询得到员工列表
        List<SysCompanyUser> companyUsers = companyUserMapper.selectList(companyUserQw);

        if (CollectionUtil.isEmpty(companyUsers)) {
            throw new NcException(ResponseEnum.USER_NOT_JOIN_COMPANY);
        }

        List<SysCompanyUserDTO> companyUserDTOS = BeanHelper.copyWithCollection(companyUsers, SysCompanyUserDTO.class);

        companyUserDTOS.forEach(companyUserDTO -> {

            LambdaQueryWrapper<SysCompanyUserRole> companyUserRoleQw = new LambdaQueryWrapper<>();
            companyUserRoleQw.eq(SysCompanyUserRole::getCompanyUserId,companyUserDTO.getId());
            companyUserRoleQw.eq(SysCompanyUserRole::getCompanyId,companyUserDTO.getCompanyId());

            List<SysCompanyUserRole> companyUserRoles = companyUserRoleMapper.selectList(companyUserRoleQw);
            if (CollectionUtil.isNotEmpty(companyUserRoles)) {

                Set<Long> roleIds = companyUserRoles.stream().map(sysCompanyUserRole -> {
                    return sysCompanyUserRole.getRoleId();
                }).collect(Collectors.toSet());

                LambdaQueryWrapper<SysRole> roleQw = new LambdaQueryWrapper<>();
                roleQw.in(SysRole::getId,roleIds);

                List<SysRole> roles = roleMapper.selectList(roleQw);

                List<SysRoleDTO> sysRoleDTOs = BeanHelper.copyWithCollection(roles, SysRoleDTO.class);


                companyUserDTO.setRoles(sysRoleDTOs);
            }



        });

        return companyUserDTOS;


    }

    @Override
    public List<SysCompanyUserDTO> queryCompanyMemberList() {
        //从线程获取企业id
        Long companyId = CurrentUserHolder.get().getCompanyId();
        //所有员工信息
        LambdaQueryWrapper<SysCompanyUser> sysCompanyUserQw = new LambdaQueryWrapper<>();
        sysCompanyUserQw.eq(SysCompanyUser::getCompanyId,companyId);
        sysCompanyUserQw.eq(SysCompanyUser::getEnable,1);
        //不包含当前用户
        sysCompanyUserQw.ne(SysCompanyUser::getId, CurrentUserHolder.get().getCompanyUserId());
        List<SysCompanyUser> sysCompanyUsers = companyUserMapper.selectList(sysCompanyUserQw);
        if(CollectionUtil.isEmpty(sysCompanyUsers)){
            throw new NcException(ResponseEnum.USER_NOT_FOUND);
        }

        List<SysCompanyUserDTO> companyUserDTOS = BeanHelper.copyWithCollection(sysCompanyUsers, SysCompanyUserDTO.class);
        return companyUserDTOS;

    }

    @Override
    public PageResult<SysCompanyUserDTO> members(Integer page, Integer pageSize, String keyword, Long departmentId) {

        Set<Long> departmentIds = new HashSet<>();

        if (departmentId==0) {
            departmentIds = this.queryAllDepartmentId();
        }else {
            departmentIds.add(departmentId);
            this.queryChildrenDepartmentIds(departmentIds, departmentId);
        }
        LambdaQueryWrapper<SysCompanyUser> sysCompanyUserQw = new LambdaQueryWrapper<>();
        sysCompanyUserQw.eq(SysCompanyUser::getCompanyId, CurrentUserHolder.get().getCompanyId());
        sysCompanyUserQw.in(SysCompanyUser::getDepartmentId,departmentIds);
        Page<SysCompanyUser> companyUserPage = new Page(page, pageSize);

        if (StrUtil.isNotEmpty(keyword)) {
            sysCompanyUserQw.and(qw->{
                qw.like(SysCompanyUser::getUserName,keyword).or().like(SysCompanyUser::getWorkNumber,keyword)
                        .or().like(SysCompanyUser::getMobile,keyword);
            });
        }

        companyUserPage = companyUserMapper.selectPage(companyUserPage, sysCompanyUserQw);

        List<SysCompanyUser> records = companyUserPage.getRecords();

        List<SysCompanyUserDTO> companyUserDTOS = BeanHelper.copyWithCollection(records, SysCompanyUserDTO.class);

        for (SysCompanyUserDTO companyUserDTO : companyUserDTOS) {
            SysDepartmentDTO sysDepartmentDTO = new SysDepartmentDTO();
            sysDepartmentDTO.setId(companyUserDTO.getDepartmentId());
            sysDepartmentDTO.setName(companyUserDTO.getDepartmentName());

            companyUserDTO.setDepartment(sysDepartmentDTO);
        }

        return new PageResult(companyUserPage.getTotal(),companyUserPage.getPages(),companyUserDTOS);

    }

    @Override
    public void importData(MultipartFile excelFile) throws IOException {
        if (excelFile == null) {
            throw new NcException(ResponseEnum.UPLOAD_FILE_NOT_FOUND);
        }

        EasyExcel.read(excelFile.getInputStream(), ExcelMember.class, new ExcelMemberListener(this)).sheet(0).doRead();

    }

    @Autowired
    HxImManager manager;

    @Autowired
    private SysUserMapper sysUserMapper;


    @Override
    public void handleParsedData(List<ExcelMember> memberList) {
        for (ExcelMember excelMember : memberList) {
            SysUser sysUser = new SysUser();
            //手机号和邮箱是否被占用
            LambdaQueryWrapper<SysUser> sysUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
            sysUserLambdaQueryWrapper.eq(SysUser::getMobile,excelMember.getMobile());
            sysUserLambdaQueryWrapper.eq(SysUser::getEmail,excelMember.getEmail());
            Integer sysUser1 = sysUserMapper.selectCount(sysUserLambdaQueryWrapper);
            if (sysUser1!=null||sysUser1!=0) {
                throw new NcException(ResponseEnum.USER_MOBILE_EMAIL_EXISTS);
            }
            //企业工号是否被占用, 懒得写
            /*int worknumberCount = companyUserMapper.checkWorknumberCount(excelMember.getWorkNumber());
            if(worknumberCount != 0){
                throw new NcException(ResponseEnum.WROK_NUM_EXISTS);
            }*/

            // 封装系统用户数据 , 对密码进行加密
            sysUser.setMobile(excelMember.getMobile());
            sysUser.setEmail(excelMember.getEmail());
            sysUser.setUsername(excelMember.getName());
            sysUser.setCreateTime(excelMember.getEntryTime());
            sysUser.setStatus(excelMember.getEnable().equals("可用")?(short)1:(short)0);
            sysUser.setPassword(new BCryptPasswordEncoder().encode("123456"));
            sysUserMapper.insert(sysUser);

            //存储企业员工数据
            SysCompanyUser companyUser = new SysCompanyUser();

            companyUser.setUserId(sysUser.getId());
            companyUser.setUserName(excelMember.getName());
            companyUser.setMobile(excelMember.getMobile());
            companyUser.setEmail(excelMember.getEmail());
            companyUser.setRemark(excelMember.getDesc());
            companyUser.setEnable(excelMember.getEnable().equals("可用")?(short)1:(short)0);
            companyUser.setPost(excelMember.getPosition());
            companyUser.setCompanyId(CurrentUserHolder.get().getCompanyId());
            companyUser.setCompanyName(CurrentUserHolder.get().getCompanyName());
            companyUser.setOfficeAddress(excelMember.getWorkAddr());
            companyUser.setTimeEntry(excelMember.getEntryTime());
            companyUser.setWorkNumber(excelMember.getWorkNumber());

            //组装部门信息
            if (StrUtil.isNotEmpty(excelMember.getDepartmentName())) {
                LambdaQueryWrapper<SysDepartment> departmentLambdaQueryWrapper = new LambdaQueryWrapper<>();
                departmentLambdaQueryWrapper.eq(SysDepartment::getCompanyId, CurrentUserHolder.get().getCompanyId());
                departmentLambdaQueryWrapper.eq(SysDepartment::getName,excelMember.getDepartmentName());
                SysDepartment sysDepartment = sysDepartmentMapper.selectOne(departmentLambdaQueryWrapper);
                if (sysDepartment!=null) {
                    companyUser.setDepartmentId(sysDepartment.getId());
                    companyUser.setDepartmentName(excelMember.getDepartmentName());
                }

            }
            companyUserMapper.insert(companyUser);

            //保存员工角色信息
            String roleName = excelMember.getRoleName();
            if (StrUtil.isNotEmpty(roleName)) {
                LambdaQueryWrapper<SysRole> roleLambdaQueryWrapper = new LambdaQueryWrapper<>();
                roleLambdaQueryWrapper.eq(SysRole::getRoleDesc,roleName);
                roleLambdaQueryWrapper.eq(SysRole::getCompanyId, CurrentUserHolder.get().getCompanyId());
                SysRole sysRole = roleMapper.selectOne(roleLambdaQueryWrapper);
                if (sysRole!=null) {
                    SysCompanyUserRole sysCompanyUserRole = new SysCompanyUserRole();
                    sysCompanyUserRole.setCompanyId(CurrentUserHolder.get().getCompanyId());
                    sysCompanyUserRole.setCompanyUserId(companyUser.getId());
                    sysCompanyUserRole.setRoleId(sysRole.getId());

                    companyUserRoleMapper.insert(sysCompanyUserRole);
                }
            }

            SysUser u = new SysUser();
            u.setUsername(sysUser.getUsername());
            u.setPassword("123456");
            manager.registerUser2HuanXing(u);
        }

    }

    @Override
    public SysCompanyUserDTO findCompanyUserByMobile(String mobile) {

        if (mobile!=null) {
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }
        LambdaQueryWrapper<SysCompanyUser> sysCompanyUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
        sysCompanyUserLambdaQueryWrapper.eq(SysCompanyUser::getMobile, mobile);
        SysCompanyUser sysCompanyUser = companyUserMapper.selectOne(sysCompanyUserLambdaQueryWrapper);
        return BeanHelper.copyProperties(sysCompanyUser, SysCompanyUserDTO.class);

    }

    @Override
    public void uploadDepartmentMysql(JSON xlsxJson) {
    //未完成,不知道请求参数
    }

    @Autowired
    SysDepartmentMapper sysDepartmentMapper;

    @Autowired
    RocketMQTemplate rocketMQTemplate;

    private void queryChildrenDepartmentIds(Set<Long> departmentIds, Long departmentId) {
        LambdaQueryWrapper<SysDepartment> sysDepartmentLambdaQueryWrapper = new LambdaQueryWrapper<>();
        sysDepartmentLambdaQueryWrapper.eq(SysDepartment::getCompanyId,CurrentUserHolder.get().getCompanyId());
        sysDepartmentLambdaQueryWrapper.eq(SysDepartment::getParentId, departmentId);
        List<SysDepartment> sysDepartments = sysDepartmentMapper.selectList(sysDepartmentLambdaQueryWrapper);

        if (CollectionUtil.isNotEmpty(sysDepartments)) {
            Set<Long> ids = sysDepartments.stream().map(sysDepartment -> {
                return sysDepartment.getId();
            }).collect(Collectors.toSet());
            departmentIds.addAll(ids);

            for (Long id : ids) {
                this.queryChildrenDepartmentIds(departmentIds,id);
            }
        }
    }

    private Set<Long> queryAllDepartmentId() {
        LambdaQueryWrapper<SysDepartment> departmentLambdaQueryWrapper = new LambdaQueryWrapper<>();

        departmentLambdaQueryWrapper.eq(SysDepartment::getCompanyId,CurrentUserHolder.get().getCompanyId());
        List<SysDepartment> sysDepartments = sysDepartmentMapper.selectList(departmentLambdaQueryWrapper);

        if (CollectionUtil.isNotEmpty(sysDepartments)) {
            Set<Long> ids = sysDepartments.stream().map(sysDepartment -> {
                return sysDepartment.getId();
            }).collect(Collectors.toSet());
            return ids;
        }
        return new HashSet<>();

    }



    @Override
    public void allowedJoinCompany(SysAllowedJoinCompanyUserDTO sysAllowedJoinCompanyUserDTO) {
        LambdaQueryWrapper<SysCompanyUser> companyUserQw = new LambdaQueryWrapper<>();
        companyUserQw.eq(SysCompanyUser::getCompanyId, CurrentUserHolder.get().getCompanyId());
        companyUserQw.eq(SysCompanyUser::getUserId,sysAllowedJoinCompanyUserDTO.getApplyUserId());

        SysCompanyUser sysCompanyUser = companyUserMapper.selectOne(companyUserQw);
        if (sysAllowedJoinCompanyUserDTO.getApproved()) {
            rocketMQTemplate.convertAndSend("allowedJoinCompanyTopic",sysAllowedJoinCompanyUserDTO.getNotifyMsgId());

            NcMessage ncMessage = new NcMessage();
            ncMessage.setApplyUserId(sysAllowedJoinCompanyUserDTO.getApplyUserId());
            ncMessage.setApplyUsername(sysCompanyUser.getUserName());
            ncMessage.setMessageType(MessageConstant.COMPANY_APPLY_PASS);
            ncMessage.setContent(sysCompanyUser.getCompanyName()+"审核通过");

            ncMessage.setApproveUserId(CurrentUserHolder.get().getId());
            ncMessage.setApplyUsername(CurrentUserHolder.get().getUsername());
            ncMessage.setTargets(Collections.singletonList(sysCompanyUser.getMobile()));

            log.info("发送信息到MQ, 推送审核通过的消息给系统管理员");
            rocketMQTemplate.convertAndSend("messagePushTopic", ncMessage);
        }

    }

    /**
     * 查询考勤组列表所有企业用户信息
     * @return
     */
    @Override
    public List<SysCompanyUserDTO> queryAllCompanyUser() {
        Long companyId = CurrentUserHolder.get().getCompanyId();
        LambdaQueryWrapper<SysCompanyUser> sysCompanyUserQw = new LambdaQueryWrapper<>();
        sysCompanyUserQw.eq(SysCompanyUser::getCompanyId, companyId);
        List<SysCompanyUser> sysCompanyUsers = companyUserMapper.selectList(sysCompanyUserQw);
        List<SysCompanyUserDTO> companyUserDTOS = BeanHelper.copyWithCollection(sysCompanyUsers, SysCompanyUserDTO.class);
        return companyUserDTOS;

    }

    //根据企业ID查询企业的主管理员信息
    @Override
    public SysCompanyUserDTO queryAdminByCompanyId(Long companyId) {
        SysCompanyUser companyUser = companyUserMapper.queryMainAdminCompanyUser(companyId);
        return BeanHelper.copyProperties(companyUser, SysCompanyUserDTO.class);
    }


}
